import { useState } from 'react'
import { message } from 'antd'
import JsCookie from 'js-cookie'
import modalConfigSecondAuth from '@/components/config/modal-second-auth'
import { IS_NEED_SECOND_AUTH } from '@/global/constant'
import { encryptData } from '@/utils/encrypt'
import { fetchSecondAuthAction } from '@/store/module/app'
import { myShallowEqual, useMyDispatch, useMySelector } from '@/store'

function usePageContent({ pageModalRef }: any) {
  // 通用
  const dispatch = useMyDispatch()
  const { publicKey, propIds, searchParams } = useMySelector(
    (state) => ({
      publicKey: state.app.publicKey,
      propIds: state.pageCommon.propIds,
      searchParams: state.pageCommon.searchConfig
    }),
    myShallowEqual
  )

  // 通用：当前modal配置
  const [curModalConfig, setCurModalConfig] = useState<any>(
    modalConfigSecondAuth
  )

  // 通用：是否是批量操作状态
  const [isBatchBanned, setIsBatchBanned] = useState<any>(false)

  // 通用：当前行数据
  const [currentRecord, setCurrentRecord] = useState<any>({})

  // 认证的具体逻辑
  function toSecondAuth(values: any) {
    const encryptStr = encryptData(publicKey, values)
    if (encryptStr) return dispatch(fetchSecondAuthAction(encryptStr))
  }

  // 通用：二级认证--判断是否需要二次认证
  function handleSecondAuth(fn: () => void) {
    if (JsCookie.get(IS_NEED_SECOND_AUTH)) {
      fn()
    } else {
      setCurModalConfig(modalConfigSecondAuth)
      pageModalRef.current?.openModal()
    }
  }

  // 通用：勾选数据--判断是否已经选中
  function handleJudgeChecked(fn: () => void) {
    if (propIds.length > 0) {
      fn()
    } else {
      message.info('请先选中数据~')
    }
  }

  return {
    // 公钥、当前批量选中的id集合、分页查询参数
    store: { publicKey, propIds, searchParams },
    // 当前的modal框配置项状态
    modal: [curModalConfig, setCurModalConfig],
    // 是否是批量操作状态
    batchBanned: [isBatchBanned, setIsBatchBanned],
    // 当前选中的行状态
    record: [currentRecord, setCurrentRecord],
    dispatch,
    // 二次认证的实现
    toSecondAuth,
    // 判断是否选中了批量数据
    handleJudgeChecked,
    // 判断是否需要二次认证
    handleSecondAuth
  }
}
export default usePageContent
/**
 * 最外层组件 -> pageContent -> lyTable
 * 1. 之所以那么快是因为有的页面相对来说比较简单，只有增删改查，但是也有一些页面有其他的操作的，
 * 比如批量删除，给用户重置密码，强制用户下线之类的。
 *    我总结一下，在二次封装完antd组件后，我还做了两件事，分别是进行动态网络请求和对立面共有的内容进行hook抽取。
 * 1.1 动态网络请求：就是很多个页面都会有相同的操作，新增改查这些接口，如果后端设计得比较好，那他路径只有一点点不一样，
 * 比如用户的分页数据就是/user/list，角色分页数据就是/role/list,所以我会多页面相同请求都只用一个函数表示，
 * 只不过在传入的时候加上一个页面特定标识符来区分，所以我并不用重复封装网络请求函数。
 * 1.2 hook的抽取：我就拿usePageContent来说吧，他会对多个页面会出现多次的一些状态或者
 * 函数进行导出。
 *    一是对仓库数据进行简化：有的页面他是有批量操作的，那么在前边二次封装好的table表格里面，
 * 当选中全部，我会把全部的id保存到了仓库里面，但是从仓库里面获取数据，我觉得过程也是有点繁琐的，
 * 因为他需要通过useSelector来拿到结果，他里面是一个函数。我会把会用到的一些仓库数据在这个hook里面导出。
 *    二是定义页面上的响应式数据，页面上有可能出现多个modal弹出框，也就是封装好的pageModal，
 * 但是这里我只是给他传入不同的配置，他的组件都是同一个。所以在新增操作或者是编辑操作，我需要
 * 用响应式数据来接收当前的配置文件。
 *    三是导出共有的函数，页面在进行"删除"这种谨慎的操作的时候，会进行二次认证，认证成功
 * 后的5分钟吧如果我没记错的话，在这个时间段内再次进行别的删除不需要重新认证。可以说，只要
 * 有删除功能的页面都需要走这个流程，所以像这种二次认证的函数我也会通过hook导出使用。
 *
 * 针对不同的组件，也就是pageSearch、pageContent、pageModal，我都使用了hook来减少重复的
 * 代码，但是思路都是一样的。我刚刚只说了pageContent表格内容的而已。
 *
 * 通过这些处理后，其实最外层做的事情是非常少的，无非就是拿到子组件传过来的某一个按钮，然后
 * 特定的参数整理，再发请求就好了。
 */

/**
 * form组件封装难点：
 *
 * 1、数据联动的问题：一个表单项值的不同会影响到另外的表单项。假如有一个单选框，如果选择是，那
 * 么下面会出现一个文本输入框；如果选择否就会隐藏输入框。想到他无非就是渲染跟不渲染的问题，那
 * 前面如果为false就是不渲染，为true就是渲染。我是通过函数执行返回这个结果的，并且把当前表单
 * 项的唯一标识传进来，也就是字段名。因为表单项的配置都需要唯一标识的，因为我们需要给表单绑定
 * 一个对象，这个对象里面的每一个属性名就对应着我们指定的字段名，因为不是所有的表单项都要进行
 * 特殊操作，所以我用字段名来区分当前当前的表单项，假如这个字段是我们要处理的，回到刚刚说的
 * 例子，我会去看一下单选框当前绑定的值是什么来决定返回true或者false，大概是这个思路。
 *
 * 2、表单里面实现自定义内容：有一些表单项他里面的内容并不是输入框，下拉框这些的。因为这个项目
 * 是跟题目有关的，会有新建题目的情况，但是题目他新建的时候可以添加标签，添加标签这种属于
 * 自定义内容。我们肯定不能直接在配置对象里面实现这样的自定义内容的。然后我就想到了父传子
 * children，因为他可以实现类似于vue插槽的效果。我直接通过prop.children来渲染内容在这个表单项
 * 的位置。但是这个时候又出现了别的问题，假如有多个表单项都需要自定义内容。假设表单第一项跟最后
 * 一项是自定义内容，第一项的内容是123，最后一项是456.如果直接通过prop.children的话会出现
 * 第一项跟最后一项都出现了123跟456的情况，也就是每一项都会把children都渲染一遍。我们希望的是
 * 第一项出现children里面那个123的节点，而最后一项出现children里面456的节点。那就是需要比对，
 * 虽然是自定义表单项，但是我这里也需要给他加上一个属于他自己的字段名，然后我再给children里面
 * 的每一个节点加上key值。然后呢，在真正渲染的时候我不是直接通过prop.chidlren, 也是返回一个
 * 函数，这个函数传入当前表单项的字段名，在函数里面我把prop.children遍历，因为children有两种
 * 情况嘛，如果只有一个节点那children就是节点，如果有多节点children就是一个数组，将每一个节点
 * 去跟传进来的字段名匹配，假如匹配就返回那个节点。这样就不会出现节点重复渲染的问题。
 */
